package com.atguigu.lease.web.app.service.impl;

import com.atguigu.lease.common.constant.RedisConstant;
import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.utils.CodeUtil;
import com.atguigu.lease.common.utils.JwtUtil;
import com.atguigu.lease.model.entity.UserInfo;
import com.atguigu.lease.model.enums.BaseStatus;
import com.atguigu.lease.web.app.mapper.UserInfoMapper;
import com.atguigu.lease.web.app.service.LoginService;
import com.atguigu.lease.web.app.service.SmsService;
import com.atguigu.lease.web.app.vo.user.LoginVo;
import com.atguigu.lease.web.app.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;


import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private SmsService smsService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserInfoMapper userInfoMapper;


    /**
     * @param phone
     * @Desceription: 获取短信验证码
     * @Return: void
     * @Author: yangchengbao
     * @Date: 2025-01-09 09:01:36
     */
    @Override
    public void getCode(String phone) {
        String randomCode = CodeUtil.getRandomCode(6);//随机生成一个6位数的验证码
        smsService.sendCode(phone, randomCode);//发送验证码
        String key = RedisConstant.APP_LOGIN_PREFIX + phone;//拼接key
        Boolean hasKey = redisTemplate.hasKey(key);//判断key是否存在
        if (hasKey) {
            Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);//获取key的剩余时间
            if (RedisConstant.APP_LOGIN_CODE_TTL_SEC - expire < RedisConstant.APP_LOGIN_CODE_RESEND_TIME_SEC) {//如果剩余时间小于60秒，则抛出异常
                throw new LeaseException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
            }
        }
        // 将验证码保存到redis中
        redisTemplate.opsForValue().set(key, randomCode, RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);


    }

    /**
     * @param loginVo
     * @Desceription: 登录
     * 前端发送手机号码phone和接收到的短信验证码code到后端。
     * 首先校验phone和code是否为空，若为空，直接响应手机号码为空或者验证码为空，若不为空则进入下步判断。
     * 根据phone从Redis中查询之前保存的验证码，若查询结果为空，则直接响应验证码已过期 ，若不为空则进入下一步判断。
     * 比较前端发送的验证码和从Redis中查询出的验证码，若不同，则直接响应验证码错误，若相同则进入下一步判断。
     * 使用phone从数据库中查询用户信息，若查询结果为空，则创建新用户，并将用户保存至数据库，然后进入下一步判断。
     * 创建JWT并响应给前端。
     * @Return: java.lang.String
     * @Author: yangchengbao
     * @Date: 2025-01-09 09:01:65
     */
    @Override
    public String login(LoginVo loginVo) {
        String phone = loginVo.getPhone();//手机号
        String voCode = loginVo.getCode();//验证码
        // 校验手机号和验证码是否为空
        if (phone == null) {
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }
        // 校验验证码是否为空
        if (voCode == null) {
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EMPTY);
        }
        String key = RedisConstant.APP_LOGIN_PREFIX + phone;
        String code = redisTemplate.opsForValue().get(key);//从redis中获取验证码
        // 校验验证码是否过期
        if (code == null) {
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EXPIRED);
        }
        // 校验验证码是否正确
        if (!voCode.equals(code)) {
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_ERROR);
        }
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getPhone, phone);
        UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);
        //检验用户是否存在
        if (userInfo == null) {
            //如果不存在，则创建新用户
            userInfo = new UserInfo();
            userInfo.setPhone(phone);
            userInfo.setStatus(BaseStatus.ENABLE);
            String substring = phone.substring(7);// 获取手机号码后四位
            userInfo.setNickname("用户-" + substring);
            userInfoMapper.insert(userInfo);
        } else {
            if (userInfo.getStatus() == BaseStatus.DISABLE) {
                throw new LeaseException(ResultCodeEnum.APP_ACCOUNT_DISABLED_ERROR);
            }

        }
        // 登录成功后删除redis中的验证码
        redisTemplate.delete(key);
        return JwtUtil.createToken(userInfo.getId(), phone);
    }

    /**
     * @param userId
     * @Desceription: 获取用户信息
     * @Return: com.atguigu.lease.web.app.vo.user.UserInfoVo
     * @Author: yangchengbao
     * @Date: 2025-01-09 10:01:26
     */
    @Override
    public UserInfoVo getUserInfoByUserId(Long userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        UserInfoVo userInfoVo = new UserInfoVo(userInfo.getNickname(), userInfo.getAvatarUrl());
        return userInfoVo;
    }
}
